<?php

    class Url {

	// list of all official tlds
	var $tlds;
	// contains the parts of the url after going through parse_url
	var $parts;
	// original url
	var $url;
	// last error message
	var $error;

        public function __construct($url) {
	    $this->url = $url;
	    $this->parts = parse_url(trim($url));
            $this->parts['paths'] = array();
            if(isset($this->parts['path'])){
                $this->parts['paths'] = array_values(array_filter(explode('/', $this->parts['path'])));
            }
            if(!isset($this->parts['query_params'])){
                $this->parts['query_params'] = array();
            }
	    // to get the updated list : http://data.iana.org/TLD/tlds-alpha-by-domain.txt
	    $this->tlds = array('AC', 'AD', 'AE', 'AERO', 'AF', 'AG', 'AI', 'AL', 'AM',
		'AN', 'AO', 'AQ', 'AR', 'ARPA', 'AS', 'ASIA', 'AT', 'AU',
		'AW', 'AX', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI',
		'BIZ', 'BJ', 'BM', 'BN', 'BO', 'BR', 'BS', 'BT', 'BV', 'BW', 'BY', 'BZ',
		'CA', 'CAT', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO',
		'COM', 'COOP', 'CR', 'CU', 'CV', 'CX', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM',
		'DO', 'DZ', 'EC', 'EDU', 'EE', 'EG', 'ER', 'ES', 'ET', 'EU', 'FI', 'FJ', 'FK',
		'FM', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE', 'GF', 'GG', 'GH', 'GI', 'GL', 'GM',
		'GN', 'GOV', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY', 'HK', 'HM', 'HN',
		'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IM', 'IN', 'INFO', 'INT', 'IO', 'IQ', 'IR',
		'IS', 'IT', 'JE', 'JM', 'JO', 'JOBS', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN',
		'KP', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT',
		'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MG', 'MH', 'MIL', 'MK', 'ML', 'MM',
		'MN', 'MO', 'MOBI', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MUSEUM', 'MV', 'MW',
		'MX', 'MY', 'MZ', 'NA', 'NAME', 'NC', 'NE', 'NET', 'NF', 'NG', 'NI', 'NL', 'NO',
		'NP', 'NR', 'NU', 'NZ', 'OM', 'ORG', 'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL',
		'PM', 'PN', 'PR', 'PRO', 'PS', 'PT', 'PW', 'PY', 'QA', 'RE', 'RO', 'RS', 'RU',
		'RW', 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM',
		'SN', 'SO', 'SR', 'ST', 'SU', 'SV', 'SY', 'SZ', 'TC', 'TD', 'TEL', 'TF', 'TG',
		'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TP', 'TR', 'TRAVEL', 'TT', 'TV', 'TW',
		'TZ', 'UA', 'UG', 'UK', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VG', 'VI', 'VN',
		'VU', 'WF', 'WS', 'XN--0ZWM56D', 'XN--11B5BS3A9AJ6G', 'XN--80AKHBYKNJ4F',
		'XN--9T4B11YI5A', 'XN--DEBA0AD', 'XN--G6W251D', 'XN--HGBK6AJ7F53BBA',
		'XN--HLCJ6AYA9ESC7A', 'XN--JXALPDLP', 'XN--KGBECHTV', 'XN--ZCKZAH',
		'YE', 'YT', 'YU', 'ZA', 'ZM', 'ZW');

	    $this->parseUrl();
	}

	// extracts the domain + tld of an url
	public function parseUrl() {

	    if (!isset($this->parts['host'])) return false;

	    $host = $this->parts['host'];

	    // extracts the 3 last dots-separated parts
	    $parts = explode('.', $host);
	    $domain_parts = array();

	    // as long as it matches a tld, we continue
	    $i = count($parts) - 1;
	    $tlds = array();
	    while(in_array(strtoupper($parts[$i]), $this->tlds)) {
		$tlds[] = $parts[$i];
		$domain_parts[] = $parts[$i];
		$i--;
	    }
	    $domain_parts[] = $parts[$i];

	    $this->parts['tlds'] = implode('.', array_reverse($tlds));
	    $this->parts['domain'] = strtolower(implode('.', array_reverse($domain_parts)));
	    if ($i > 0)
		    $this->parts['subdomain'] = implode('.', array_slice($parts, 0, $i));

	    // handling querystring
	    if (isset($this->parts['query'])) {
		parse_str($this->parts['query'], $output);
		$this->parts['query_params'] = array_map('html_entity_decode', $output);
	    }

	    // depending on the scheme, we add the port number
	    if (!isset($this->parts['port']) or !$this->parts['port']) {
		if (!isset($this->parts['scheme'])) $this->parts['scheme'] = false;

		switch($this->parts['scheme']) {
		    case 'https':
			$this->parts['port'] = 443;
			break;
		    case 'ftp':
			$this->parts['port'] = 21;
			break;
		    case 'http':
		    default:
			$this->parts['port'] = 80;
			break;
		}
	    }
	}

	// formats an url according to Synthesio's method : http://(www.)+domain.tld/path
	public function cleanUrl() {
	    if (!in_array($this->parts['scheme'], array('http', 'https'))) {
		$this->error = 'Scheme should be http or https';
		return false;
	    }

	    // url always starts with "http://"
	    $formatted_url = 'http://';

	    // replaceing "www2" and "www3" by "www"
	    if (isset($this->parts['subdomain'])) {
		$subdomain = $this->parts['subdomain'];

		if (in_array($subdomain, array('www2', 'www3'))) {
		    $subdomain = 'www';
		}

		// removing the unecessary "www." if we have a "multiple subdomain" (eg : http://www.gonon2007.blogspot.com )
		if (strpos($subdomain, '.')) {
		    $subdomain = explode('.', $subdomain);
		    if ($subdomain[0] == 'www' and count($subdomain) > 1) {
			unset($subdomain[0]);
		    }
		    $subdomain = implode('.', $subdomain);
		}

		// if we have a subdomain, we add it to the final url
		if ($subdomain) {
		    $formatted_url .= $subdomain.'.';
		}
	    }

	    // we add the domain name
	    $formatted_url .= $this->parts['domain'];

	    // we add the port number
	    if (isset($this->parts['port']) and $this->parts['port'] != 80) {
		$formatted_url .= ':'.$this->parts['port'];
	    }

	    // we add the path
	    $formatted_url .= $this->parts['path'];

	    // we add the query
	    if (isset($this->parts['query']))
		    $formatted_url .= '?'.http_build_query($this->parts['query_params']);

	    // we remove the final hash
	    while(substr($formatted_url, -1) == '/') {
		$formatted_url = substr($formatted_url, 0, -1);
	    }

	    return $formatted_url;
	}

	// formats an url according to Synthesio's method : http://www.domain.tld
	static public function domainUrl($url) {

	    if (!trim($url)) return false;

	    $url = new Url($url);
	    $formatted_url = '';

	    // replacing "www2" and "www3" by "www"
	    $subdomain = isset($url->parts['subdomain']) ? $url->parts['subdomain'] : '';

	    if (!$subdomain) $subdomain = 'www';

	    if (in_array($subdomain, array('www2', 'www3'))) {
		$subdomain = 'www';
	    }

	    // removing the unecessary "www." if we have a "multiple subdomain" (eg : http://www.gonon2007.blogspot.com )
	    if (strpos($subdomain, '.')) {
		$subdomain = explode('.', $subdomain);
		if ($subdomain[0] == 'www' and count($subdomain) > 1) {
		    unset($subdomain[0]);
		}
		$subdomain = implode('.', $subdomain);
	    }

		// if we have a subdomain, we add it to the final url
	    if ($subdomain) {
		$formatted_url .= $subdomain.'.';
	    }

	    // we add the domain name
	    $formatted_url .= $url->parts['domain'];

	    return $formatted_url;
	}

    }

?>
